import os
import numpy
import pandas as pd
import sympy as sp
from sympy import symbols, Eq, solve, im
import math

def tand(x):
    return sp.tan(x * sp.pi / 180)
def sind(x):
    return sp.sin(x * sp.pi / 180)
def cosd(x):
    return sp.cos(x * sp.pi / 180)
def cotd(x):
    return sp.cot(x * sp.pi / 180)
def sqrt(x):
    return math.sqrt(x)
def cos(x):
    return math.cos(x)
def sin(x):
    return math.sin(x)

"""constants"""
pi = math.pi
j  = 1j
Z0 = 120*pi
"""constants"""

"""Physical Constants"""
e0 = 8.85e-12                       # Permittivity of free space (epsilon-not)
c0 = 1 / sqrt(4*pi*1e-7 * e0)       # Velocity of light in free space (air or vaccum)
"""Physical Constants"""

"""Inputs"""
phaseShift   = 30       # The desired phase shift we want. Real world angle shift of em waves
freq         = 10.5e9   # Designing for 10.5 GHz atenna, can be altered
inputAngle   = 0        # 
outputAngle  = 80       #
polarization = 'TM'     # Can be either TM or TE
"""Inputs"""

"""Substrate Constants"""
Ls               = {             # Subtrate thickness constant specific to substrate
    "Rogers RO3003" : 1.52e-3,
    "Rogers RO3010" : 1.28e-3}
substratePermits = {             # Relative permeativity of RO3010.
    "Rogers RO3003" : 3,
    "Rogers RO3010" : 10.2}
"""Substrate Constants"""

"""bondply constants"""
Lbp           = 0.076e-3   # Bondply thickness constant specific to substrate
bondplyPermit = 2.94       # Bondply permeativity
betabp = sqrt(bondplyPermit) * 2*pi / (c0/freq)     # wavenumber in the substrate for bondply
Zcbp = Z0/ sqrt(bondplyPermit)                      # characteristic impedance for bondply
"""bondply constants"""

# function to take in the two output files from HFSS in s value and return z values
def convert_svals(sMat,trace,material):
    
    substratePermit = substratePermits[material]
    L = Ls[material]
    
    print(substratePermit, ":", L)
    
    beta = sqrt(substratePermit)*2*pi/(c0/freq) # Wavenumber in the substrate
    Zc = Z0 / sqrt(substratePermit) # Characteristic impedance of substrate. Different than Z0.

    Y1,Y2,Y3 = sp.symbols("Y1, Y2, Y3")
    
    T11 = ((1/(2*sMat[1,0]))*((1 + sMat[0,0])*(1 - sMat[1,1]) + sMat[0,1]*sMat[1,0])).evalf()
    T12 = ((Z0/(2*sMat[1,0]))*((1 + sMat[0,0])*(1 + sMat[1,1]) - sMat[0,1]*sMat[1,0])).evalf()
    T21 = ((1/(Z0*2*sMat[1,0]))*((1 - sMat[0,0])*(1 - sMat[1,1]) - sMat[0,1]*sMat[1,0])).evalf()
    T22 = ((1/(2*sMat[1,0]))*((1 - sMat[0,0])*(1 + sMat[1,1]) + sMat[0,1]*sMat[1,0])).evalf()
    
    tMat = sp.Matrix([[T11,T12],[T21,T22]])
    
    T4 = sp.Matrix([[cos(beta*L), j*Zc*sin(beta*L)],
                    [j*sin(beta*L)/Zc, cos(beta*L)]])
    
    bondply = sp.Matrix([[cos(betabp*Lbp), j*Zcbp*sin(betabp*Lbp)],
                         [j*sin(betabp*Lbp)/Zcbp, cos(betabp*Lbp)]])
    
    if(trace == "top"):
        solvedT = tMat/T4/bondply/T4
        
    elif(trace == "mid"):
        x = bondply.LUsolve(T4.LUsolve(tMat))/T4
        solvedT = x
        
    elif(trace == "bot"):
        #solvedT=T4.inv()*bondply.inv()*T4.inv()*tMat
        x = T4.LUsolve(bondply).LUsolve(T4).LUsolve(tMat)
        solvedT = x
        
    # TODO: Calculate simulation metric from solvedT

    Yval = solvedT[1,0].evalf()
    Impedance = (1/Yval).evalf()
    
    return im(Impedance)